<?php

/**
 * @package Nina
 * @author John Main <john@thedaddy.org>
 */
class Nina_Orm_Subquery
{
	/**
	 * The primary model the subquery will be built around
	 * @var Nina_Model
	 */
	protected $obj;

	/**
	 * The subquery criteria
	 * @var Nina_Orm_Criteria
	 */
	protected $criteria;

	/**
	 * The fields we wish to select (if none are given then all will be selected)
	 * @var array
	 */
	protected $fields = array();

	/**
	 * Constructor
	 * @param Nina_Model $obj The primary model the subquery will be built around
	 */
	public function __construct($obj) {
		$this->obj = $obj;
		$this->criteria = new Nina_Orm_Criteria();
		$this->criteria->setDb($obj->getDb());
		$this->criteria->addTable($obj->getClass());
	}
	
	/**
	 * Add a field to select
	 * @param string $field The field name
	 */
	public function addField($field) {
		$this->fields[] = $field;
	}
	
	/**
	 * Define the set of fields to select
	 * @param array $fields The field names
	 */
	public function setFields($fields) {
		$this->fields = $fields;
	}
	
	/**
	 * Get the class
	 * @return string
	 */
	public function getClass() {
		return $this->obj->getClass();
	}
	
	/**
	 * Create the select clause
	 * @return string
	 */
	public function createSelectClause() {
		if($this->fields) {
			$fields = $this->fields;
		}
		else {
			$fields = array();

			//Add all the fields of this model to the select
			foreach ($this->obj->getFieldNames() as $field) {
				$select_field = $this->criteria->replaceSelectField($field);
				$fields[] = $select_field . " AS `" . str_replace('`', '', $field) . "`";
			}
			//Any special select replacements (e.g. count, max, min etc) that aren't on the main model (and hence the primary table) need to be added in manually as they may well be used for sorting, grouping etc
			foreach($this->criteria->getSpecialSelects() as $field => $operation) {
				$fields[] = $operation .'(' . $field . ')' . " AS `" . str_replace('`', '', $field) . "`";
			}
		}

		return implode("," . PHP_EOL, $fields) . PHP_EOL;
	}
	
	/**
	 * Create the subquery statement
	 * @return string
	 */
	public function createStatement() {
		$sql = 'SELECT ' . $this->createSelectClause() . ' FROM ' . $this->criteria->createFromClause() . ' WHERE ' . $this->criteria->createWhereClause();
		
		if ($stmt = Nina_Orm_Base::prepare($this->obj, $sql)) {
			$this->criteria->commit($stmt);
			return $stmt->getSql();
		}
	}
	
	/**
	 * Any unknown calls are sent direct to the Nina_Orm_Criteria object
	 * @param string $method Method name
	 * @param array $args The arguments
	 * @return mixed
	 */
	public function __call($method, $args) {
		return call_user_func_array(array($this->criteria, $method), $args);
	}
}
